package com.szsh.aiot.hsm.service.impl;

import com.google.gson.Gson;
import com.szsh.aiot.common.core.domain.AjaxResult;
import com.szsh.aiot.common.utils.TimeTools;
import com.szsh.aiot.framework.influxdb.CameraInfluxService;
import com.szsh.aiot.hsm.domain.IUserDevice;
import com.szsh.aiot.hsm.domain.camera.ICameraAccess;
import com.szsh.aiot.hsm.domain.camera.ICameraRemindsetting;
import com.szsh.aiot.hsm.domain.IFlowDevice;
import com.szsh.aiot.hsm.domain.camera.CameraAbnormalModel;
import com.szsh.aiot.hsm.domain.camera.CameraDevice;
import com.szsh.aiot.hsm.domain.camera.DeviceInfo;
import com.szsh.aiot.hsm.domain.camera.SingleCameraAbnormal;
import com.szsh.aiot.hsm.dto.SubscribeSyncInfo;
import com.szsh.aiot.hsm.dto.ability.AbilityResponse;
import com.szsh.aiot.hsm.dto.enu.OrderSyncOpType;
import com.szsh.aiot.hsm.dto.enu.PluginOperateAction;
import com.szsh.aiot.hsm.dto.plugin.IPluginInfo;
import com.szsh.aiot.hsm.dto.ability.TopoInfo;
import com.szsh.aiot.hsm.dto.camera.*;
import com.szsh.aiot.hsm.dto.enu.FlagType;
import com.szsh.aiot.hsm.dto.enu.NameSource;
import com.szsh.aiot.hsm.dto.gateway.GatewayInfo;
import com.szsh.aiot.hsm.dto.gateway.IBroadbandServicesInfo;
import com.szsh.aiot.hsm.dto.gateway.IPluginInstallRet;
import com.szsh.aiot.hsm.enums.DeviceType;
import com.szsh.aiot.hsm.enums.IdentityType;
import com.szsh.aiot.hsm.mapper.*;
import com.szsh.aiot.hsm.service.CameraAccessService;
import com.szsh.aiot.hsm.thirdService.AbilityClient;
import com.szsh.aiot.hsm.thirdService.DeviceInfoClient;
import com.szsh.aiot.hsm.thirdService.GatewayInfoQueryClient;
import com.szsh.aiot.hsm.thirdService.MkReportClient;
import com.szsh.aiot.hsm.utils.Hash163;
import com.szsh.aiot.hsm.utils.SubscribeInfoSyncProcess;
import org.apache.commons.lang3.StringUtils;
import org.influxdb.InfluxDB;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Description:摄像头访问提醒Service
 * @Date 2023/8/25: 14:33
 * @Author: LOADING>>>>>
 */

@Service
public class CameraAccessServiceImpl implements CameraAccessService {

    private static final Logger LOGGER = LoggerFactory.getLogger(CameraAccessServiceImpl.class);

    @Value("${hsm.plugin.b01Version}")
    private int b01Version;


    @Autowired
    private Hash163 hash163;

    @Autowired
    private GatewayInfoQueryClient gatewayClient;

    @Autowired
    private ICameraAccessMapper cameraAccessMapper;

    @Autowired
    private IUserDeviceMapper userDeviceMapper;

    @Autowired
    private IFlowDeviceMapper flowDeviceMapper;

    @Autowired
    private IPluginInfoMapper pluginInfoMapper;

    @Autowired
    private CameraInfluxService cameraInflux;

    @Autowired
    private ICameraRemindsettingMapper remindSettingMapper;

    @Autowired
    private DeviceInfoClient deviceInfoClient;

    @Autowired
    private MkReportClient mkReportClient;

    @Autowired
    private InfluxDB influxDB;

    @Autowired
    private AbilityClient abilityClient;

    @Autowired
    private IBroadbandServicesInfoMapper broadbandServicesInfoMapper;

    @Autowired
    private IBatchUpgradeDetailMapper batchUpgradeDetailMapper;

    @Autowired
    private IPluginInstallRetMapper installMapper;

    @Autowired
    private SubscribeInfoSyncProcess subscribeInfoSyncProcess;

    @Autowired
    private Gson gson;



    @Override
    public AjaxResult getCameraAbnormal(String broadbandNO, String gatewayMac, String pushReason) {

        List<SingleCameraAbnormal> abnormalList = new ArrayList<>();
        LOGGER.info("camera异常信息查询broadbandNO[{}]---pushReason[{}]", broadbandNO, pushReason);

        // 网关信息
        GatewayInfo gatewayInfo = gatewayClient.queryByPPOE(broadbandNO);
        if (gatewayInfo == null || StringUtils.isEmpty(gatewayInfo.getPhone())) {
            return AjaxResult.error("网关未查询到绑定关系");
        }

        // 获取展示摄像头设备列表
        List<IUserDevice> cameraList = getCameraList(broadbandNO, gatewayMac);
        if (cameraList.isEmpty()) {
            return AjaxResult.error("未查询到相关数据");
        }

        // 查询摄像头异常信息
        cameraList.forEach(device -> {
            SingleCameraAbnormal abnormal = new SingleCameraAbnormal();
            abnormal.setName(device.getShowName());
            abnormal.setIsOnline(device.getIsOnline());
            abnormal.setDeviceId(device.getDeviceID());
            if (StringUtils.isNotBlank(device.getDeviceMac())){
                abnormal.setDeviceMac(device.getDeviceMac());
            }
            abnormal.setDeviceMac(device.getDeviceMac());
            // 一键保护还是一键恢复
            abnormal.setButtonFlag(device.getButtonFlag());

            // 根据手机号码和设备mac查询3天内的摄像头异常信息
            List<CameraAbnormal> cameraAbnormalList = null;
            try {
                cameraAbnormalList = cameraInflux.getAbnormalList(gatewayInfo.getPhone(),
                        device.getDeviceMac(), pushReason);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            abnormal.setAbnormal(convert2model(cameraAbnormalList));
            abnormalList.add(abnormal);

        });
        return AjaxResult.success("获取数据成功",abnormalList);
    }

    @Override
    public AjaxResult queryRemindSetting(String broadbandNO) {
        ICameraRemindsetting cameraRemindSetting = remindSettingMapper.selectICameraRemindsettingByBroadbandNO(broadbandNO);
        // 未设置
        if (cameraRemindSetting == null) {
            return AjaxResult.error("未查询到相关信息");
        }
        Map<String,Integer> setting = new HashMap<>();
        setting.put("setting",cameraRemindSetting.getSetting());
        return AjaxResult.success("查询数据成功",setting);
    }


    @Override
    public AjaxResult updateRemindSetting(String broadbandNO, Integer setting) {
        int ret = 0;

        LOGGER.info("camera设置更新broadbandNO[{}]，设置[{}]", broadbandNO, setting);
        ICameraRemindsetting iCameraRemindsetting = new ICameraRemindsetting();
        iCameraRemindsetting.setSetting(setting);
        iCameraRemindsetting.setBroadbandNO(broadbandNO);
        ICameraRemindsetting querySetting = remindSettingMapper.selectICameraRemindsettingByBroadbandNO(broadbandNO);
        if (querySetting == null) {
            ret = remindSettingMapper.insertICameraRemindsetting(iCameraRemindsetting);
        } else {
            ret = remindSettingMapper.updateICameraRemindsetting(iCameraRemindsetting);
        }
       if (ret == 0){
           return AjaxResult.error("处理失败");
       }
       return AjaxResult.success("处理成功");
    }

    @Override
    public AjaxResult getDeviceList(String broadbandNO, String gatewayMac) {

        List<CameraDevice> resultList = new ArrayList<>();
        // 获取已选择的设备
        LinkedHashMap<Long, CameraDevice> choseMap = new LinkedHashMap<>();
        ICameraAccess iCameraAccess = new ICameraAccess();
        iCameraAccess.setBroadbandNO(broadbandNO);
        List<ICameraAccess> accessList = cameraAccessMapper.selectICameraAccessList(iCameraAccess);

        accessList.forEach(access -> {
            CameraDevice cameraDevice = new CameraDevice();
            cameraDevice.setDeviceId(access.getDeviceId());
            cameraDevice.setDeviceName(access.getDeviceName());
            cameraDevice.setChose(1);
            choseMap.put(access.getDeviceId(), cameraDevice);
        });

        // 拓扑接口查询设备
        List<TopoInfo> topoDeviceList = deviceInfoClient.getTopoList(gatewayMac);
        for (TopoInfo topo : topoDeviceList) {
            IUserDevice userDevice = getUserDevice(broadbandNO, topo);

            CameraDevice choseCameraDevice = choseMap.get(userDevice.getDeviceID());
            if (null != choseCameraDevice) {
                // 已经选择 防止名称为空
                if (org.apache.commons.lang3.StringUtils.isBlank(choseCameraDevice.getDeviceName())) {
                    // 名称为空
                    choseCameraDevice.setDeviceName("智能设备" + org.apache.commons.lang3.StringUtils.right(userDevice.getDeviceMac(), 4));
                }
                continue;
            }

            CameraDevice cameraDevice = new CameraDevice();
            cameraDevice.setDeviceId(userDevice.getDeviceID());

            String showName = userDevice.getShowName();
            if (org.apache.commons.lang3.StringUtils.isBlank(showName)) {
                // showName 名称为空
                cameraDevice.setDeviceName("智能设备" + org.apache.commons.lang3.StringUtils.right(userDevice.getDeviceMac(), 4));
            } else {
                cameraDevice.setDeviceName(showName);
            }

            resultList.add(cameraDevice);
        }
        // 保存
        resultList.addAll(0, choseMap.values());

        LOGGER.info("获取设备列表:{}", new Gson().toJson(resultList));
        return AjaxResult.success("获取数据成功",resultList);
    }

    @Override
    public AjaxResult saveDeviceInfo(List<String> deviceIdList, String broadbandNO) {

        try {
            // 删除之前设置的设备列表，并且上报迈科
            deleteDeviceInfo(broadbandNO);
            // 删除保存列表信息
            cameraAccessMapper.deleteICameraAccessByBroadbandNO(broadbandNO);
            // 保存新的列表信息,上报迈科
             int insetResult = save(deviceIdList, broadbandNO);

             if (insetResult ==0){
                 return AjaxResult.error("保存列表信息失败");
             }
            return AjaxResult.success("保存列表信息成功");
        } catch (Exception e) {
            LOGGER.error("设置摄像头异常访问列表失败{}", e);
            return AjaxResult.error("保存失败");
        }
    }

    @Override
    public AjaxResult setAttachDevice(String gateMac, String deviceMac, String deviceName, String buttonFlag) {
        return null;
    }

    @Override
    public AjaxResult getFlowDevice(String broadbandNO, String gatewayMac) {

        List<DeviceInfo> deviceList = new ArrayList<>();

        List<IFlowDevice> flowList = flowDeviceMapper.selectIFlowDeviceListByBroadBand(broadbandNO,gatewayMac);
        if (!flowList.isEmpty()) {
            // 显示用户选择的设备
            for (IFlowDevice flowDevice : flowList) {
                DeviceInfo info = new DeviceInfo();
                info.setType(flowDevice.getDeviceType());
                info.setDeviceName(flowDevice.getDeviceName());
                info.setDeviceId(flowDevice.getDeviceId());
                info.setChose(1);
                deviceList.add(info);
            }
        }
        return AjaxResult.success("查询成功",deviceList);

    }

    @Override
    public AjaxResult getFlowPushData(String deviceid) {
        try {
            PictureDataModel successModel = PictureDataModel.returnSuccess();
            List<List<Object>> flowPushList = getFlowPushList(deviceid);
            successModel.setDatalist(flowPushList);
            List<List<Object>> alarmPushList = getFlowAlarmData(deviceid);
            successModel.setAlarmlist(alarmPushList);
            return AjaxResult.success("查询成功",successModel);
        } catch (Exception e) {
            LOGGER.error("influxDB query err,{}", e);
            return AjaxResult.badRequest("查询失败");
        }
    }

    @Override
    public AjaxResult getOnlineDeviceList(String broadbandNO, String gatewayMac) {
        List<DeviceInfo> deviceInfoList = new ArrayList<>();
        try {
            // 已经选择的
            deviceInfoList = getFlowDeviceFromDB(broadbandNO);

            // 拓扑接口查询在线设备
            List<TopoInfo> topoInfoList = deviceInfoClient.getOnlineTopoList(gatewayMac);
            Map<Long, IUserDevice> userDeviceMap = new LinkedHashMap<>();
            for (TopoInfo topoInfo : topoInfoList) {
                IUserDevice userDevice = getUserDevice(broadbandNO, topoInfo);

                userDeviceMap.put(userDevice.getDeviceID(), userDevice);
            }

            // 增加 离线 状态
            for (DeviceInfo deviceInfo : deviceInfoList) {
                IUserDevice userDevice = userDeviceMap.remove(deviceInfo.getDeviceId());
                if (null == userDevice) {
                    // 设备不在线
                    String deviceName = deviceInfo.getDeviceName();
                    deviceInfo.setDeviceName(deviceName + "(离线)");
                }
            }

            // 添加剩余的
            for (IUserDevice userDevice : userDeviceMap.values()) {
                DeviceInfo device = new DeviceInfo();
                device.setDeviceId(userDevice.getDeviceID());
                device.setDeviceName(userDevice.getShowName());
                device.setType(getDeviceType(userDevice.getShowName()));
                // 未选择
                device.setChose(0);
                deviceInfoList.add(device);
            }
        } catch (Exception e) {
            LOGGER.error("查询用户[{}]设备列表异常,", broadbandNO, e);
        }
        LOGGER.info("broadbandNO:[{}],gwMac:[{}].设备列表：{}", broadbandNO, gatewayMac, new Gson().toJson(deviceInfoList));
        return  AjaxResult.success("查询成功",deviceInfoList);

    }

    @Override
    public AjaxResult setUpFlowDevice(String broadbandNO, List<String> deviceidList) {

        int ret = 0;
        try {
            GatewayInfo gatewayInfo = gatewayClient.queryByPPOE(broadbandNO);
            // B01插件操作
            sendPluginToKafka(gatewayInfo, IdentityType.MAIKE);
            // 先通知迈科删除设备mac
            IFlowDevice queryflowDevice = new IFlowDevice();
            queryflowDevice.setBroadbandNO(broadbandNO);
            List<IFlowDevice> flowDevices = flowDeviceMapper.selectIFlowDeviceList(queryflowDevice);
            for (IFlowDevice flowDevice : flowDevices) {
                deleteFlowDevice(flowDevice);
            }
            // 然后删除本地数据库中设置的检测设备
            flowDeviceMapper.deleteByBroadbandNO(broadbandNO);
            // 再重新导入监测设备列表
            for (int i = 0; i < deviceidList.size(); i++) {
                long deviceId = Long.parseLong(deviceidList.get(i));
                // 新增数据
                ret += insterFlowDevice(broadbandNO, deviceId);
            }
        } catch (Exception e) {
            LOGGER.error("用户[{}]设备设备列表失败", broadbandNO, e);
            return  AjaxResult.error("保存设备列表失败");
        }
        return AjaxResult.success("成功",ret);

    }

    private void deleteFlowDevice(IFlowDevice info) {
        IUserDevice userDevice = userDeviceMapper.selectIUserDeviceByDeviceID(info.getDeviceId());
        if (userDevice == null) {
            return;
        }
        String deviceName = userDevice.getShowName();
        String type = null;
        if (deviceName.contains("摄像")) {
            type = "camera";
        }
        if (deviceName.contains("天翼摄像") || userDevice.getDeviceType() == 1) {
            // 或者设备表明确表示是天翼摄像头
            type = "tycamera";
        }
        if (deviceName.contains("音箱") || deviceName.contains("音响") || deviceName.contains("门铃")) {
            type = "other";
        }
        if (!StringUtils.isEmpty(type)) {
            LOGGER.info("deviceID{{}],deviceName{{}},deviceMac[{}],通知迈科删除设备mac",
                    userDevice.getDeviceID(), deviceName, userDevice.getDeviceMac());
            mkReportClient.mkReport(userDevice.getDeviceMac(), type, "delete");
        }
    }

    private int insterFlowDevice(String broadbandNO, Long deviceId) {
        IFlowDevice info = new IFlowDevice();
        IUserDevice userDevice = userDeviceMapper.selectIUserDeviceByDeviceID(deviceId);
        if (userDevice != null){
            String deviceName = userDevice.getShowName();
            String showName =  userDevice.getShowName();
            info.setBroadbandNO(broadbandNO);
            info.setDeviceName(deviceName);
            userDevice.setShowName(showName);
            info.setDeviceType(getDeviceType(showName));
            info.setCreateTime(new Date());
            if(org.apache.commons.lang3.StringUtils.isNotBlank(userDevice.getDeviceMac())){
                info.setDeviceMac(userDevice.getDeviceMac());
            }
            mkReport(info, userDevice, "add");
            return flowDeviceMapper.insertIFlowDevice(info);
        }
       return 0;
    }

    private void mkReport(IFlowDevice info, IUserDevice userDevice, String add) {
        String type = "other";
        if (info.getDeviceType() == DeviceType.CAMERA.getVal()) {
            if (userDevice.getShowName().contains("摄像")) {
                type = "camera";
            }
            if (userDevice.getShowName().contains("天翼摄像")) {
                type = "tycamera";
            }
        }
        LOGGER.info("mkReport broadbandNO[{}],deviceMac[{}],deviceType[{}]",
                userDevice.getBroadbandNO(), userDevice.getDeviceMac(), type);
        mkReportClient.mkReport(userDevice.getDeviceMac(), type, add);
    }




    /**
     * 获取展示摄像头设备列表
     * @param broadbandNO
     * @param gatewayMac
     * @return
     */
    private List<IUserDevice> getCameraList(String broadbandNO, String gatewayMac) {
        List<IUserDevice> cameraList = new ArrayList<>();
        // 查询用户自定义设置设备列表
        ICameraAccess cameraAccess = new ICameraAccess();
        cameraAccess.setBroadbandNO(broadbandNO);
        List<ICameraAccess> accessList = cameraAccessMapper.selectICameraAccessList(cameraAccess);

        if (accessList == null || accessList.isEmpty()) {
            return cameraList;
        }

        for (ICameraAccess cameraInfo : accessList) {
            IUserDevice userDevice = userDeviceMapper.selectIUserDeviceByDeviceID(cameraInfo.getDeviceId());
            if (userDevice != null) {
                cameraList.add(userDevice);
            }
        }
        return cameraList;
    }

    /**
     * influxDB查询结果转换为页面model
     *
     * @param abnormalList
     * @return
     */
    private List<CameraAbnormalModel> convert2model(List<CameraAbnormal> abnormalList) {
        List<CameraAbnormalModel> modelList = new ArrayList<>();
        abnormalList.forEach(abnormal -> {
            CameraAbnormalModel model = new CameraAbnormalModel();
            model.setTstamp(Date.from(abnormal.getTime()));
            model.setSourceIP(abnormal.getSourceIP());
            model.setSourceArea(abnormal.getSourceArea());
            model.setPushReason(abnormal.getPushReason());
            modelList.add(model);
        });
        return modelList;
    }

    /**
     * 保存用户设备
     *
     * @param broadbandNO
     * @param topo
     * @return
     */
    private IUserDevice getUserDevice(String broadbandNO, TopoInfo topo) {
        // 查询设备是否存在
        IUserDevice userDevice = userDeviceMapper.selectIUserDeviceByMac(broadbandNO, topo.getMac());

        if (userDevice == null) {
            String devName = StringUtils.isEmpty(topo.getDevname()) ? topo.getModel()
                    : topo.getDevname();
            userDevice = new IUserDevice();
            userDevice.setBroadbandNO(broadbandNO);
            userDevice.setDeviceMac(topo.getMac());
            userDevice.setDeviceName(devName);
            userDevice.setShowName(devName);
            userDevice.setNameSource(NameSource.WG.getType());
            userDevice.setIpv4add(topo.getIp());
            userDevice.setIsOnline(topo.getActive());
            userDevice.setIsGateway(FlagType.NO.getVal());
            userDevice.setReceiveTime(new Date());
            userDeviceMapper.insertIUserDevice(userDevice);
        }
        return userDevice;
    }

    /**
     * 删除用户自定义摄像头异常访问设备列表 通知迈科删除设备
     *
     * @param broadbandNO
     *            宽带账号
     */
    private void deleteDeviceInfo(String broadbandNO) {

        ICameraAccess iCameraAccess = new ICameraAccess();
        iCameraAccess.setBroadbandNO(broadbandNO);
        List<ICameraAccess> accessList = cameraAccessMapper.selectICameraAccessList(iCameraAccess);
        for (ICameraAccess cameraAccess : accessList) {
            IUserDevice userDevice = userDeviceMapper.selectIUserDeviceByDeviceID(cameraAccess.getDeviceId());
            if (userDevice == null) {
                continue;
            }
            String deviceName = userDevice.getShowName();
            String type = getType(userDevice, deviceName);
            if (StringUtils.isEmpty(type)) {
                continue;
            }
            LOGGER.info("deviceID{{}],deviceName{{}},deviceMac[{}],通知迈科删除设备mac",
                    userDevice.getDeviceID(), deviceName, userDevice.getDeviceMac());
            mkReportClient.mkReport(userDevice.getDeviceMac(), type, "delete");
        }
    }

    private String getType(IUserDevice userDevice, String deviceName) {
        String type = null;
        if (deviceName.contains("摄像")) {
            type = "camera";
        }
        if (deviceName.contains("天翼摄像") || userDevice.getDeviceType() == 1) {
            type = "tycamera";
        }
        if (deviceName.contains("音箱") || deviceName.contains("音响")) {
            type = "other";
        }
        return type;
    }

    /**
     * 保存用户自定义摄像异常访问设备设备信息 通知迈科添加设备
     *
     * @param deviceIdList
     *            用户自定义设备列表
     * @param broadbandNO
     *            宽带账号
     */
    private int save(List<String> deviceIdList, String broadbandNO) {
        int ret = 0;
        for (String deviceId : deviceIdList) {
            IUserDevice userDevice = userDeviceMapper.selectIUserDeviceByDeviceID(Long.parseLong(deviceId));
            String deviceName = userDevice.getShowName();
            String type = getType(userDevice, deviceName);
            ICameraAccess cameraAccess = new ICameraAccess();
            cameraAccess.setBroadbandNO(broadbandNO);
            cameraAccess.setCreateTime(TimeTools.getNow());
            cameraAccess.setDeviceId(Long.parseLong(deviceId));
            cameraAccess.setDeviceName(deviceName);
            cameraAccessMapper.insertICameraAccess(cameraAccess);
            if (!StringUtils.isEmpty(type)) {
                LOGGER.info("deviceID{{}],deviceName{{}},deviceMac[{}],通知迈科添加设备mac",
                        userDevice.getDeviceID(), deviceName, userDevice.getDeviceMac());
                mkReportClient.mkReport(userDevice.getDeviceMac(), type, "add");
            }
            ret++;
        }
        return ret;
    }

    /**
     * 查询influxDB，返回流量推送数据集合
     *
     * @param deviceID
     * @return
     */
    private List<List<Object>> getFlowPushList(String deviceID) {
        // 查询近一天的流量数据
        // 按照20分钟为间隔查询，influxDB自动求和；该查询会多查一条前一天开始时间取整的数据
        StringBuilder querySB = new StringBuilder();
        querySB.append(
                        "select sum(\"txBytes\")/1024 as txBytes from flow_push where hashDeviceID='")
                .append(hash163.sHash(deviceID)).append("' and deviceID=").append(deviceID)
                .append(" and time>now()-1d")
                .append(" group by time(20m) fill(0) tz('Asia/Shanghai')");
        LOGGER.info("influxDB query:{}", querySB);
        Query query = new Query(querySB.toString());
        QueryResult queryResult = influxDB.query(query);
        List<QueryResult.Result> results = queryResult.getResults();
        if (results == null) {
            return new ArrayList<>();
        }
        QueryResult.Result result = results.get(0);
        List<QueryResult.Series> rsp = result.getSeries();
        if (rsp != null) {
            return rsp.get(0).getValues();
        }
        return new ArrayList<>();
    }
    /**
     * 查询influxDB流量告警信息 从告警表中获取时间 从推送数据中获取流量
     *
     * @param deviceid
     * @return
     */
    private List<List<Object>> getFlowAlarmData(String deviceid) {
        List<List<Object>> resultList = new ArrayList<>();
        // 流量告警信息
        List<List<Object>> alarmList = getFlowAlarmList(deviceid);
        if (alarmList == null || alarmList.isEmpty()) {
            return resultList;
        }
        // 查询流量推送信息
        for (int i = 0; i < alarmList.size(); i++) {
            String date = (String) alarmList.get(i).get(0);
            StringBuilder querySB = new StringBuilder();
            querySB.append("select first(\"txBytes\")/1024 as txBytes from flow_push where "
                            + "hashDeviceID='").append(hash163.sHash(deviceid)).append("' and deviceID=")
                    .append(deviceid).append(" and time='").append(date)
                    .append("' tz('Asia/Shanghai')");
            LOGGER.info("influxDB query:{}", querySB);
            Query query = new Query(querySB.toString());
            QueryResult queryResult = influxDB.query(query);
            List<QueryResult.Result> results = queryResult.getResults();
            if (results != null && results.get(0).getSeries() != null) {
                resultList.addAll(results.get(0).getSeries().get(0).getValues());
            }
        }
        return resultList;
    }

    /**
     * 查询最新流量告警信息，最多5条
     *
     * @param deviceID
     * @return
     */
    private List<List<Object>> getFlowAlarmList(String deviceID) {
        List<List<Object>> alarmList = new ArrayList<>();
        StringBuilder alarmQuery = new StringBuilder();
        // 查询最近5条流量告警信息
        alarmQuery.append("select * from flow_alarm where hashDeviceID='")
                .append(hash163.sHash(deviceID)).append("' and deviceID=").append(deviceID)
                .append(" and time>now()-1d order by time desc limit 5 tz('Asia/Shanghai')");
        LOGGER.info("influxDB query:{}", alarmQuery);
        Query query = new Query(alarmQuery.toString());
        QueryResult queryResult = influxDB.query(query);
        List<QueryResult.Result> results = queryResult.getResults();
        if (results == null) {
            return null;
        }
        QueryResult.Result result = results.get(0);
        List<QueryResult.Series> rsp = result.getSeries();
        if (rsp != null) {
            alarmList = rsp.get(0).getValues();
        }
        return alarmList;
    }
    /**
     * 返回用户设备列表信息
     *
     * @param broadbandNO
     * @return
     */
    private List<DeviceInfo> getFlowDeviceFromDB(String broadbandNO) {
        List<DeviceInfo> deviceList = new ArrayList<>();
        IFlowDevice flowDevice = new IFlowDevice();
        flowDevice.setBroadbandNO(broadbandNO);
        List<IFlowDevice> flowList = flowDeviceMapper.selectIFlowDeviceList(flowDevice);
        if (!flowList.isEmpty()) {
            // 显示用户选择的设备
            for (IFlowDevice iFlowDevice : flowList) {
                DeviceInfo info = new DeviceInfo();
                info.setType(iFlowDevice.getDeviceType());
                info.setDeviceName(iFlowDevice.getDeviceName());
                info.setDeviceId(iFlowDevice.getDeviceId());
                info.setChose(1);
                deviceList.add(info);
            }
        }
        return deviceList;
    }

    private int getDeviceType(String name) {
        if (name.contains("摄像")) {
            return DeviceType.CAMERA.getVal();
        } else if (name.contains("音箱")) {
            return DeviceType.VOICEBOX.getVal();
        } else {
            return DeviceType.OTHER.getVal();
        }
    }

    /**
     * 插件安装统一入口，将网关信息转换为kafka消息，并发送至kafka
     *
     * @param gatewayInfo
     */
    public void sendPluginToKafka(GatewayInfo gatewayInfo, IdentityType type) {
        if (gatewayInfo == null) {
            LOGGER.error("网关信息为空，无法安装插件");
            return;
        }
        PluginKafka pluginKafka = new PluginKafka();
        pluginKafka.setIdentity(type.getType());
        pluginKafka.setBroadbandNO(gatewayInfo.getPppoename());
        pluginKafka.setGateMac(gatewayInfo.getMac());
        pluginKafka.setModel(gatewayInfo.getModel());
        pluginKafka.setChipModel(gatewayInfo.getChipModel());
        pluginKafka.setProvinceName(gatewayInfo.getProvinceName());
        String msg = new Gson().toJson(pluginKafka);
        LOGGER.info("send plugin to kafka: {}", msg);
        pluginInstall(pluginKafka);
    }

    /**
     * 插件安装
     *
     * @param pluginKafka
     */
    public void pluginInstall(PluginKafka pluginKafka) {
        // 插件信息
        IPluginInfo pluginInfo = pluginInfoMapper.getPluginInfo(pluginKafka.getModel(),
                pluginKafka.getChipModel(), pluginKafka.getIdentity());
        if (pluginInfo == null) {
            LOGGER.error("用户{}网关暂无支持的插件", pluginKafka.getBroadbandNO());
            // 无支持网关
            updatePluginByNO(pluginKafka.getBroadbandNO(), 99, pluginKafka.getIdentity());
            installResult(pluginKafka, -99, "用户网关暂无支持的插件");
            return;
        }
        pluginKafka.setPluginName(pluginInfo.getPluginName());
        pluginKafka.setPluginVersion(pluginInfo.getPluginVersion());
        // 是否已安装
        if (abilityClient.isInstall(pluginKafka.getGateMac(), pluginKafka.getPluginName(),
                pluginKafka.getPluginVersion(), pluginKafka.getIdentity())) {
            LOGGER.info("用户[{}]插件已安装.gatewayMac:[{}],pluginName:[{}],pluginVersion:[{}],identity:[{}]",
                    pluginKafka.getBroadbandNO(), pluginKafka.getGateMac(), pluginKafka.getPluginName(),
                    pluginKafka.getPluginVersion(), pluginKafka.getIdentity());
            // 更新安装结果
            updatePluginflag(pluginKafka, true);
            //如果是B01插件，安装成功后要调用采集接口进行订购
           //TODO
            orderSync(pluginKafka);
            return;
        }
       AbilityResponse result = sendInstallReq(pluginKafka, pluginInfo);
        boolean installRet = "0".equals(result.getStatus()) && result.getResult() >= 0;
        LOGGER.info("用户[{}]调用插件安装接口{}", pluginKafka.getBroadbandNO(), installRet ? "成功" : "失败");
        // 记录插件安装
        installResult(pluginKafka, installRet ? result.getResult() : -9999, result.getFailReason());
        if (installRet) {
            // 发往查询队列，确认是否正确安装
      /*    //TODO
        if (pluginKafka != null) {
                pluginService.pluginEnd(pluginKafka, waitTime);
            }
            resendKafka(KafkaTopic.PLUGIN1, pluginKafka);*/
        }
        // 插件下发失败，更新安装结果到i_account
        updatePluginflag(pluginKafka, installRet);
    }

    /**
     * 更新用户插件安装状态
     *
     * @param pluginInfo
     * @param isInstall
     */
    private void updatePluginflag(PluginKafka pluginInfo, boolean isInstall) {
        String broadbandNO = pluginInfo.getBroadbandNO();
        // 安装失败
        int pluginflag = -1;
        if (isInstall) {
            // 已安装
            pluginflag = 1;
        }
        // 更新用户插件安装状态
        LOGGER.info("更新用户[{}]插件安装状态[{}]", broadbandNO, pluginflag);
        updatePluginByNO(broadbandNO, pluginflag, pluginInfo.getIdentity());
    }
    /**
     * 更新用户插件安装状态
     *
     * @param pluginflag
     * @param broadbandNO
     * @param type
     * @return
     */
    public int updatePluginByNO(String broadbandNO, int pluginflag, int type) {
        IBroadbandServicesInfo broadbandServicesInfo = new IBroadbandServicesInfo();
        broadbandServicesInfo.setBroadband(broadbandNO);
        if (type == 1) {
            broadbandServicesInfo.setSafePluginflag((long) pluginflag);
        }
        if (type == 2) {
            broadbandServicesInfo.setMkPluginflag((long) pluginflag);
        }
        broadbandServicesInfo.setUpdateTime(new Date());

        return broadbandServicesInfoMapper.updateIBroadbandServicesInfo(broadbandServicesInfo);
    }

    /**
     * B01插件下发成功且为36版本，需要同步至增值平台
     *
     * @param info
     */
    private void orderSync(PluginKafka info) {
        if (info.getIdentity() == IdentityType.MAIKE.getType()){
            if(getLastVer(info.getPluginVersion()) >= b01Version) {
                LOGGER.info("用户[{}]B01插件版本为[{}]，需要进行增值平台业务同步", info.getBroadbandNO(),
                        info.getPluginVersion());
                SubscribeSyncInfo syncInfo = new SubscribeSyncInfo();
                // 订购
                syncInfo.setOptype(OrderSyncOpType.SUB.getVal());
                syncInfo.setBroadband(info.getBroadbandNO());
                syncInfo.setGatewayMac(info.getGateMac());
                String kafkaMsg = new Gson().toJson(syncInfo);
                LOGGER.info("send ordersync to kafka: {}", kafkaMsg);
                // 增值平台业务通知
             //   kafkaTemplate.send(KafkaTopic.ORDER, kafkaMsg);
                subscribeInfoSyncProcess.subscribeInfoSync(syncInfo);
            } else {
                LOGGER.info("用户[{}]安装B01插件版本为[{}]插件，不需要进行增值平台业务同步", info.getBroadbandNO(),
                        info.getPluginVersion());
            }
        }
    }

    /**
     * 调用接口进行插件安装
     *
     * @param pluginKafka
     * @param pluginInfo
     * @return
     */
   private AbilityResponse sendInstallReq(PluginKafka pluginKafka, IPluginInfo pluginInfo) {
        LOGGER.info("用户[{}]安装插件：[{}]，版本[{}]", pluginKafka.getBroadbandNO(),
                pluginInfo.getPluginName(), pluginInfo.getPluginVersion());
        AbilityResponse result = null;
        try {
            result = abilityClient.pluginOperate(pluginKafka.getGateMac(),
                    pluginKafka.getPluginName(), pluginKafka.getPluginVersion(),
                    PluginOperateAction.INSTALL.getKey());
            // 36版本插件需要手动调用接口进行开启配置
            if (pluginKafka.getIdentity() == IdentityType.MAIKE.getType()
                    && getLastVer(pluginInfo.getPluginVersion()) >= b01Version) {
                abilityClient.pluginOperate(pluginKafka.getGateMac(), pluginKafka.getPluginName(),
                        pluginKafka.getPluginVersion(), PluginOperateAction.START.getKey());
            }
        } catch (Exception e) {
            LOGGER.error("网关MAC{}调用安装插件接口超时,", pluginKafka.getGateMac(), e);
            result = new AbilityResponse();
            result.setStatus("-1");
            result.setFailReason("调用安装插件接口超时");
        }
        return result;
    }


    /**
     * 插件安装结果入库
     *
     * @param info
     * @param result
     * @param failReason
     */
    private void installResult(PluginKafka info, int result, String failReason) {
        LOGGER.info("记录用户[{}]调用插件安装接口的返回结果...", info.getBroadbandNO());
        IPluginInstallRet ret = new IPluginInstallRet();
        ret.setBroadbandNO(info.getBroadbandNO());
        ret.setGatewayMac(info.getGateMac());
        ret.setGatewayModel(info.getModel());
        ret.setPluginName(info.getPluginName());
        ret.setPluginVersion(info.getPluginVersion());
        ret.setIdentity(info.getIdentity());
        ret.setInstallTime(new Date());
        ret.setInstallResult(result);
        ret.setFailReason(failReason);
        installMapper.insert(ret);
    }

    /**
     * 最后一次查询，更新安装结果
     *
     * @param info
     * @param wait
     */
    public void pluginEnd(PluginKafka info, int wait) {
        try {
            waitTime(info, wait);
            boolean install = abilityClient.isInstall(info.getGateMac(), info.getPluginName(),
                    info.getPluginVersion(),info.getIdentity());
            if (install) {
                // 插件安装成功，下发全量扫描
               // completescan(info);
                orderSync(info);
                LOGGER.info("用户[{}]插件安装成功", info.getBroadbandNO());
            } else {
                LOGGER.info("用户[{}]插件安装失败", info.getBroadbandNO());
            }
            //更新插件升级状态
            batchUpgradeDetailMapper.updateStatus(install ? 1 : 0,install ? "插件安装成功" : "插件安装失败", info.getSerNO());
            // 更新安装结果
            updatePluginflag(info, install);
            installMapper.updateThirdQuery(install ? 1 : 0, info.getGateMac(), info.getIdentity());
        } catch (InterruptedException e) {
            LOGGER.error("第三次查询[{}]的插件安装结果,更新安装结果异常,",info.getBroadbandNO(), e);
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 返回版本号码的最后一段小版本号
     * @return
     */
    public static int getLastVer(String version) {
        String[] verArr = version.split("\\.");
        return Integer.parseInt(verArr[verArr.length - 1]);
    }

    /**
     * 计算等待时间
     *
     * @param info
     * @throws InterruptedException
     */
    private void waitTime(PluginKafka info, int wait) throws InterruptedException {
        long now = System.currentTimeMillis();
        long count = (now - info.getSendTime()) / 1000;
        if (count < wait) {
            Thread.sleep((wait - count) * 1000);
        }
    }


}
